package com.danicsoft.daide.command;

import java.util.List;

import com.danicsoft.daide.token.StandardToken;
import com.danicsoft.daide.token.TokenGroup;
import com.danicsoft.daide.token.TokenMap;
import com.danicsoft.daide.token.TokenMap.Commands;

/**
 * Implements the DRW command. From Eric Wald's <a
 * href="http://pydip.brainshell.org/docs/syntax.html">protocol specification</a>,
 * v0.14:
 * <h4><a name="DRW">client_command = DRW</a></h4>
 * <p>
 * This command is sent by the player to the server, to indicate that the player
 * would accept a DIAS draw at this point. The server responds with <b>YES (DRW)</b>,
 * or <b>REJ (DRW)</b> if the game has not started.
 * </p>
 * <p>
 * <b>DRW</b> can also be sent from the server to the client, to indicate that
 * a draw has been declared. This will happen as soon as all non-eliminated
 * players have simultaneously indicated that they will accept a draw at that
 * point.
 * </p>
 * <p>
 * If a turn processes after <b>DRW</b> is sent from the player to the server,
 * then the command is ignored. The player must resend the command each turn if
 * it continues to want a draw.
 * </p>
 * <p>
 * If the player changes its mind, it can clear its request for a draw with
 * <b>NOT (DRW)</b>. The server will respond with <b>YES (NOT (DRW))</b>, or
 * <b>REJ (NOT (DRW))</b> if the game has not started.
 * </p>
 * <p>
 * In a <b>PDA</b> variant game, the player can send the <b>DRW</b> command
 * with a parameter &mdash; the list of powers in the draw:
 * </p>
 * <h4>{PDA} client_command = DRW (power power power ...)</h4>
 * <p>
 * If all surviving powers submit a <b>DRW</b> command with the same list of
 * powers on the same turn, then a draw is immediately declared including those
 * powers.
 * </p>
 * <p>
 * Multiple <b>DRW</b> commands may be submitted; each one does <em>not</em>
 * supersede previous <b>DRW</b> messages. Instead, it adds an additional draw
 * combination which the power will accept.
 * </p>
 * <p>
 * The server will respond to each <b>DRW</b> message with <b>YES (DRW (power
 * power power ...))</b>, or <b>REJ (DRW (power power power ...))</b> if the
 * game has not started, or if the list of powers includes an eliminated power.
 * </p>
 * <p>
 * When a draw is declared in a <b>PDA</b> variant game, the draw message
 * includes a parameter &mdash; the list of powers in the agreed draw.
 * </p>
 * <p>
 * The player may still send a <b>DRW</b> command without a parameter in a
 * <b>PDA</b> game &mdash; it is the same as sending a <b>DRW</b> command
 * listing all surviving powers.
 * </p>
 * <p>
 * The player can cancel a partial draw request with <b>NOT (DRW (power power
 * power ...))</b>.
 * </p>
 */
public class DrawCommand extends QueryableCommand {

	/**
	 * The list of powers this draw is between. Null if it is between all
	 * remaining powers.
	 */
	private List<StandardToken> drawnPowers;

	/**
	 * Construct a new <code>DrawCommand</code> from the tokens given.
	 * 
	 * @param tokens
	 *        The tokens to construct this from. It should be empty.
	 * @throws ParseException
	 *         If the list of powers given is not a valid list.
	 */
	public DrawCommand(TokenGroup tokens) throws ParseException {
		super(tokens);
	}

	/**
	 * Construct a new <code>DrawCommand</code> for suggesting a draw or
	 * accepting one.
	 */
	public DrawCommand() {
		super(true);
	}

	/**
	 * Construct a new Draw request for a draw between the given powers.
	 * @param powers
	 */
	public DrawCommand(List<StandardToken> powers) {
		super(false);
		drawnPowers = powers;
	}

	@Override
	public byte getType() {
		return Commands.DRW;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("A draw between ");
		if(isQuery()) {
			sb.append("all remaining powers.");
		} else {
			for(int i = 0; i < drawnPowers.size() - 2; i++) {
				sb.append(drawnPowers.get(i)).append(", ");
			}
			if(drawnPowers.size() >= 2) {
				sb.append(drawnPowers.get(drawnPowers.size() - 2));
				sb.append(" and ");
			}
			if(drawnPowers.size() >= 1) {
				sb.append(drawnPowers.get(drawnPowers.size() - 1));
				sb.append('.');
			}
		}
		return sb.toString();
	}

	@Override
	protected void doNonQueryIO(TokenIO tokenIO, TokenGroup tokens) throws ParseException {
		drawnPowers = tokenIO.doTokenList(tokens, drawnPowers, TokenMap.powers);

	}

}
